/**************************************************************************
** Yabet is bloging editor tool that supports many blog's formats. It is very usefull for crossposting, allows easily to
** make posts to your blogs.
**
** Copyright (C) 2010 Valery Konchin <eeexception@gmail.com>
**
** This program is free software: you can redistribute it and/or modify
**     it under the terms of the GNU General Public License as published by
**     the Free Software Foundation, either version 3 of the License, or
**     (at your option) any later version.
**
**     This program is distributed in the hope that it will be useful,
**     but WITHOUT ANY WARRANTY; without even the implied warranty of
**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**     GNU General Public License for more details.
**
**     You should have received a copy of the GNU General Public License
**     along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "yabet.h"
#include <QTextDocument>
#include "defaulthtmlyabettextmarkup.h"
#include <QRegExp>
#include "universalyabettextmodifier.h"
#include "bulletlistyabettextmodifier.h"
#include "yabettextmodifier.h"
#include <QRegExp>
#include <QFile>

const YabetLogHandler* Yabet::log = new YabetLogHandler("Yabet");

Yabet::Yabet()
{
    manager = new MarkupManager();
    this->defaultMarkup = new DefaultHtmlYabetTextMarkup();
    this->currentMarkup = new DefaultHtmlYabetTextMarkup();

    gTranslater = new GoogleTranslater();
    imageUploader = new ImageShackImageUploader();

    this->changed = false;

    connect(gTranslater, SIGNAL(wasError(QString)), this, SIGNAL(wasWarning(QString)));
    connect(imageUploader, SIGNAL(wasError(QString)), this, SIGNAL(wasWarning(QString)));
    connect(imageUploader, SIGNAL(uploadProgress(qint64,qint64)), this, SIGNAL(uploadProgress(qint64,qint64)));
}

void Yabet::setDefaultMarkup(YabetTextMarkup* markup) {
    this->defaultMarkup = markup;
}

YabetTextMarkup* Yabet::getDefaultMarkup() {
    return defaultMarkup;
}

void Yabet::setCurrentMarkup(YabetTextMarkup *markup) {
    this->currentMarkup = markup;
}

YabetTextMarkup* Yabet::getCurrentMarkup() {
    return currentMarkup;
}

MarkupManager* Yabet::getMarkupManager() {
    return manager;
}

void Yabet::setEditorText(QTextDocument * document) {
    this->document = document;

//    QString bodyStart = "<body style=\" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;\">";
//    int position = document->toHtml().indexOf(bodyStart);
//    htmlStart = document->toHtml().left(position + bodyStart.length());
//
//    position = document->toHtml().indexOf("</body>");
//    htmlStop = document->toHtml().mid(position);
//
//    log->debugMsg("Start html: \n" + htmlStart);
//    log->debugMsg("Stop html: \n" + htmlStop);
}

void Yabet::setTopic(QString topic) {
    this->topic = topic;
}

void Yabet::modifyText(QString markupElementName, int from, QString textToModify) {
    YabetTextModifier *modifier = new UniversalYabetTextModifier(currentMarkup->getMarkupElement(markupElementName));

    QString modifiedText = modifier->modifyText(QStringList(textToModify));

    log->debugMsg("Text to replace:\n" + modifiedText);

    log->debugMsg("Replace from: " + QString::number(from, 10) + "; Length: " + QString::number(textToModify.length(), 10));
    QString replacedText =  document->toPlainText().replace(from, textToModify.length(), modifiedText);
    //QString replacedText =  document->toHtml().replace(from, textToModify.length(), modifiedText);

    log->debugMsg("Replaced text:\n" + replacedText);

    document->setPlainText(replacedText);
//    document->setHtml(replacedText);
}

void Yabet::modifyText(QString markupElementName, int from, int to, QStringList textsToModify) {
    YabetTextModifier *modifier = new UniversalYabetTextModifier(currentMarkup->getMarkupElement(markupElementName));

    QString modifiedText = modifier->modifyText(textsToModify);

    document->setPlainText(document->toPlainText().replace(from, to - from, modifiedText));
    //document->setHtml(document->toHtml().replace(from, to - from, modifiedText));
}

void Yabet::insertCode(int from, QString textToModify) {
    YabetTextModifier *modifier = new UniversalYabetTextModifier(currentMarkup->getMarkupElement(YabetTextMarkup::CODE_ELEMENT_NAME));

    QString modifiedText = modifier->modifyText(QStringList(textToModify));

    document->setPlainText(document->toPlainText().replace(from, textToModify.length(), modifiedText));
    //document->setHtml(document->toHtml().replace(from, textToModify.length(), modifiedText));
}

void Yabet::insertBulletList(int from, QString textToModify) {
    YabetTextModifier *modifier = new BulletListYabetTextModifier(currentMarkup->getMarkupElement(YabetTextMarkup::LIST_ELEMENT_NAME));

    QString modifiedText = modifier->modifyText(textToModify.split(QChar::ParagraphSeparator, QString::SkipEmptyParts));

    document->setPlainText(document->toPlainText().replace(from, textToModify.length(), modifiedText));
    //document->setHtml(document->toHtml().replace(from, textToModify.length(), modifiedText));
}

void Yabet::convertHtmlTags(int from, int to) {
    QString textToConvert = document->toPlainText().mid(from, to-from);
    QString convertedText = textToConvert.replace(QRegExp("&"), "&amp;");
    convertedText = convertedText.replace(QRegExp("\""), "&quot;");
    convertedText = convertedText.replace(QRegExp("<"), "&lt;");
    convertedText = convertedText.replace(QRegExp(">"), "&gt;");
    convertedText = convertedText.replace(QRegExp(" "), "&nbsp;");
    convertedText = convertedText.replace(QRegExp("\t"), "&nbsp;&nbsp;&nbsp;&nbsp;");

    document->setPlainText(document->toPlainText().replace(from, textToConvert.length(), convertedText));
    //document->setHtml(document->toHtml().replace(from, textToConvert.length(), convertedText));
}

QString Yabet::getText() {
    //QString plainText = document->toHtml();
    QString plainText = document->toPlainText();

//    plainText = plainText.replace("\n", "<br/>\n", Qt::CaseSensitive);

    return plainText;
}

QString Yabet::getTopic() {
    return topic;
}

void Yabet::translateText(QString text, QString fromLanguage, QString toLanguage, int from) {
    QString translatedText = gTranslater->translate(text, fromLanguage, toLanguage);

    if(translatedText.isEmpty() == false) {
        document->setPlainText(document->toPlainText().replace(from, text.length(), translatedText));
        //document->setHtml(document->toHtml().replace(from, text.length(), translatedText));
    }
}


GoogleTranslater* Yabet::getGoogleTranslater() {
    return gTranslater;
}

QString Yabet::getBuildDate() {
    return YabetVersion::BUILD_DATE;
}

QString Yabet::getVersion() {
    return YabetVersion::MAJOR_VERSION + "." + YabetVersion::MINOR_VERSION;
}

void Yabet::newFile() {
    topic = "";
    document->clear();
    document->setHtml("");
    //document->
    filename = "";
}

void Yabet::openFile(QString filename) {
    QFile file(filename);

    if(!file.open(QIODevice::ReadOnly)) {
        //todo
        return;
    }

    QString data = data.fromUtf8(file.readAll());

    int topicEnd = data.indexOf("\n");
    topic = data.left(topicEnd);
    //document->setHtml(data.mid(topicEnd + 1));
    document->setPlainText(data.mid(topicEnd + 1));
    file.close();

    this->filename = filename;
}

void Yabet::saveFile(QString filename) {
    if(filename.indexOf(".ybt") == -1) {
        filename.append(".ybt");
    }

    QFile file(filename);

    if(!file.open(QIODevice::WriteOnly)) {
        //todo
        return;
    }

    QByteArray data;
    data.append(topic.toUtf8());
    data.append("\n");
    data.append(document->toPlainText().toUtf8());
    //data.append(document->toHtml().toUtf8());

    file.write(data);

    file.close();

    this->filename = filename;
}

void Yabet::setFilename(QString filename) {
    this->filename = filename;
}

QString Yabet::getFilename() {
    return filename;
}

bool Yabet::isChanged() {
    return changed;
}

void Yabet::change(bool changed) {
    this->changed = changed;
}

QString Yabet::uploadImage(QString fileName, QString fileHosting) {
    QString resultUrl = imageUploader->uploadImage(fileName, fileHosting);

    return resultUrl;
}
